/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pr2.cruce;

import java.util.List;
import pr2.cromosoma.CromosomaPVC;

/**
 *
 * @author Gonzalo Ortiz Jaureguizar (gortiz at software.imdea.org)
 */
public class PXM extends EstrategiaCruce<CromosomaPVC> {

    int p1, p2;

    public PXM(int size) {
        super(size);
    }

    public PXM() {
    }

    @Override
    protected void cruzar(CromosomaPVC padre1, CromosomaPVC padre2, CromosomaPVC hijo1, CromosomaPVC hijo2) {
        elegirPuntos(padre1.getGenes().size());

        int distancia = p2 - p1;
        
        if(distancia == 1 || distancia == padre1.getGenes().size()) {
            hijo1.copia(padre1);
            hijo2.copia(padre2);
            return ;
        }

        List<Integer> pg1 = padre1.getGenes();
        List<Integer> pg2 = padre2.getGenes();
        List<Integer> hg1 = hijo1.getGenes();
        List<Integer> hg2 = hijo2.getGenes();
        
        intercambiar(pg1, pg2, hg1, hg2);

        copiaEmparejada(pg1, pg2, hg1, hg2);
    }

    private void elegirPuntos(int size) {
        p1 = (int) (Math.random() * size);
        p2 = (int) (Math.random() * size);

        if(p1 > p2) {
            int aux = p1;
            p1 = p2;
            p2 = aux;
        }
        p2++; //para coger el ultimo!
    }

    private void intercambiar(List<Integer> padre1, List<Integer> padre2, List<Integer> h1, List<Integer> h2) {
        for(int i = p1; i < p2; i++) {
            h1.set(i, padre2.get(i));
            h2.set(i, padre1.get(i));
        }
    }

    private void copiaEmparejada(List<Integer> padre1, List<Integer> padre2, List<Integer> h1, List<Integer> h2) {
        int i;
        for(i = 0; i < p1; i++) {
            Integer v;

            v = getNuevoValor(padre1, padre2, i);
            h1.set(i, v);

            v = getNuevoValor(padre2, padre1, i);
            h2.set(i, v);
        }
        for(i = p2; i < padre1.size(); i++) {
            Integer v;

            v = getNuevoValor(padre1, padre2, i);
            h1.set(i, v);

            v = getNuevoValor(padre2, padre1, i);
            h2.set(i, v);
        }
    }

    /**
     * Si valor esta entre los cruzados de otroPadre, entonces devuelve la pareja, en otro caso devuelve valor
     * @param padre1
     * @param padre2
     * @param valor
     * @return
     */
    private Integer getNuevoValor(List<Integer> padre1, List<Integer> padre2, int i) {
        int valor = padre1.get(i);
        for(int j = p1; j < p2; j++) {
            if(padre2.get(j) == valor)
//                return padre1.get(j);
                return getNuevoValor(padre1, padre2, j); //hay que hacerlo recurrente ¬¬
        }
        return valor;
    }


}
